/* ===================================
 * vtkView共用方法 创成云
 * Created by py on 2022/03/11.
 * Copyright 2022, Inc.
 * TypeScript 混入、类型推断、交叉类型、联合类型、声明合并、
 * =================================== */
import * as THREE from "three";
import html2canvas from "html2canvas";
import { IChild, IControl, IBControl } from "./MyTempInterface";
// import { updateThumbnail } from '@/api/modules/task';
import { logger } from "../utils/logger";
import { Line2 } from "three/examples/jsm/lines/Line2";
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls";
import { TrackballControls } from "three/examples/jsm/controls/TrackballControls";
import {
  // addEventHandler,
  base64ToBlob,
  downloadFileByNewWindow,
  hasOwnProperty,
  isArray,
  isEmptyObject,
} from "../utils/utils";
import {
  BJ_POINT_GROUP,
  SelectModeEnum,
  ColorEnum,
  DISPERSED_LINE_GROUP,
  FACE_GROUP,
  RESULT_WATER_COOLING_GROUP,
  SOLID_GROUP,
  WIREFRAME,
  YS_LINE_GROUP,
} from "../constants";

// -------------------------------------
// 此类属性不能放vue data 里，
// 不然严重影响性能问题，卡顿掉帧严重
let scene: THREE.Scene,
  canvas: HTMLCanvasElement,
  arrowScene: THREE.Scene,
  arrowCanvas: HTMLCanvasElement,
  renderer: THREE.WebGLRenderer,
  perspectiveCamera: THREE.PerspectiveCamera,
  orthographicCamera: THREE.OrthographicCamera,
  perspectiveControls: OrbitControls | TrackballControls,
  orthographicControls: OrbitControls | TrackballControls,
  arrowRenderer: THREE.WebGLRenderer,
  arrowCamera: THREE.Camera,
  cameraType: number | string, // Perspective、Orthographic
  controlType: string, // OrbitControls、TrackballControls
  cameraCenter: THREE.Vector3;
// -------------------------------------

export const ControlTypeEnum = {
  Orbit: "OrbitControls",
  Trackball: "TrackballControls",
};
 /**
     * 删除场景内对象
     * @param {THREE.Object3D|THREE.Object3D[]} children
     */
 export const removeSceneObj=(children: any)=> {
    if (!children) return;
    if (isArray(children)) {
      scene.remove(...children);
    } else {
      scene.remove(children);
    }
    children = null;
  }
     /**
     * 按条件获取预设线对象及控制点对象
     * @param {String} groupName
     * @return {{spheres: *, ysLine}}
     */
    export function  getYsLineObjectAndSphereByGroupName(groupName: string) {
        let ysLine;
        const spheres = scene.children.filter(
          (child: any) => child.groupName === groupName
        );
        const ysLineGroup = this.getGroupByName(YS_LINE_GROUP);
        if (ysLineGroup) {
          ysLine = ysLineGroup.children.find(
            (child: any) => child.nickname === groupName
          );
        }
        return { spheres, ysLine };
      }
export const defaultData = {
  tip: "",
  loading: false,
  background: [0.2, 0.2, 0.2, 0.2],
  jsViewWidth: "calc(100vw - 320px)",

  selectPart: SelectModeEnum.solid,
  originColor: ColorEnum.black,
  originOpacity: 1,
  originVisible: true,
  selectedColor: ColorEnum.white,
  selectParam: null,
  selectTarget: null,
  curActiveObj: null,
  direction: null,
  currentActiveItem: null,

  // ThreeJs About
  renderRequested: false,
  far: 100000, // 值太小，边缘线会出现虚线! 用于照相机焦点设置（焦点距离，越大越精确）
  cameraType: "Perspective",
  pointer: new THREE.Vector2(),
  clientX: 0,
  clientY: 0,
  lastZoom: -1,
  plane: undefined,
  mouse: {
    LEFT: THREE.MOUSE.PAN,
    RIGHT: THREE.MOUSE.ROTATE,
  },
  zoomSpeed: 0, // 要实现自己的鼠标滚轮事件,必须禁用THREE.TrackballControls的默认缩放
  openAnimate: false,
  camToSave: {
    Perspective: {
      controlCenter:{}
    },
    Orthographic: { controlCenter:{}},
  },

  taskId: "", // 任务id
  projectId: "", // 项目id
  solidNames: [],

  curDraw: "",
  curAction: "",
  pointList: [],
  circleMap: {},
  pointCount: 0,
  curveCount: 0,
  brokenLineCount: 0,
  circleCount: 0,
  singleSpiralLineCount: 0,
  doubleHelixLineCount: 0,
  curvesMap: {},
  drawing: false,
  initPosition: null,

  // 临时数据
  tempSpheresGroup: new THREE.Group(),
  tempCurvesGroup: new THREE.Group(),
  // 正式数据
  spheresGroup: new THREE.Group(),
  curvesGroup: new THREE.Group(),

  long: 0, // 计算长
  modelLong: 0, // 模型长
  jsonData: {},
  rulerLoaded: false,
  contextMenuObject: null,
  hiddenObjectMap: {},
  intersectObjects: [],
  zList: [],

  scrolled: false,
  isMoved: false,
  loadingCount: 0,
  openBoxSelecting: false,
  rightMenuVisible: false,
  fileName: "",
};
  /**
     * 按条件获取场景子项
     * @param {String} groupName
     * @param {Function=} condition
     * @return {THREE.Object3D[]|*[]}
     */
 export function  getSceneChildrenByCondition(
    groupName: string,
    condition = (child: any) => child
  ) {
    const group = this.getGroupByName(groupName);
    if (!group) return [];
    return group.children.filter((child) => condition(child));
  }
    /**
     * 获取场景所有结果对象
     * @return {THREE.Object3D[]|*[]}
     */
  export function   getSceneAllResultObjs(condition = (child) => true) {
      return  getSceneChildrenByCondition(
        RESULT_WATER_COOLING_GROUP,
        condition
      );
    }
    /**
     * 创建或更新组
     * @param {String} groupName
     * @param {Object=} attrs
     */
    export function createOrUpdateGroup(groupName: string, attrs = []) {
      let group =  getGroupByName(groupName);
      if (!group) {
        group = new THREE.Group();
        group.name = groupName;
        if (typeof attrs === "object" && !isEmptyObject(attrs)) {
          for (const key in attrs) {
            group.userData = attrs[key];
          }
        }
        scene.add(group);
      }
      return group;
    }
  /**
     * 获取当前控制器
     * @return {OrbitControls|TrackballControls}
     */
  export const getCurrControl=()=> {
    let controls;
    if (cameraType === "Orthographic") {
      controls = orthographicControls;
    }
    if (cameraType === "Perspective") {
      controls = perspectiveControls;
    }
    return controls;
  }

/**
 * 初始化控器制属性
 * @param {OrbitControls|TrackballControls} control
 * @param {String} type
 */
export const initControlAttribute = (
  control: IControl | IBControl,
  type = "OrbitControls"
) => {
  debugger
  if (type === "OrbitControls") {
    //@ts-ignore
    defaultData.openAnimate = false;
    // OrbitControls attr
    // 使动画循环使用时阻尼或自转 意思是否有惯性
    control.enableDamping = false;
    // 是否可以缩放
    control.enableZoom = true;
    // 是否自动旋转
    control.autoRotate = false;
    // // 设置相机距离原点的最远距离
    // control.minDistance = 200;
    // // 设置相机距离原点的最远距离
    // control.maxDistance = 600;
    // 限制最大仰视角和俯视角
    control.minPolarAngle = 0; // 你能够垂直旋转的角度的下限，范围是0到Math.PI，其默认值为0
    control.maxPolarAngle = Math.PI; // 你能够垂直旋转的角度的上限，范围是0到Math.PI，其默认值为Math.PI
    // 是否开启右键拖拽
    //@ts-ignore
    control.enablePan = defaultData.mouse.RIGHT === THREE.MOUSE.PAN;
    // 否允许鼠标左键旋转场景
    //@ts-ignore
    control.enableRotate = defaultData.mouse.RIGHT === THREE.MOUSE.ROTATE;
  } else {
    //@ts-ignore
    defaultData.openAnimate = true;
    // TrackballControls attr
    // 旋转的速度，其默认值为1.0
    control.rotateSpeed = 20.0;
    // 缩放的速度，其默认值为1.2
    //@ts-ignore
    control.zoomSpeed = defaultData.mouse.RIGHT === THREE.MOUSE.ROTATE ? 0 : 3;
    // control.zoomSpeed = 0.0; // 要实现自己的鼠标滚轮事件,必须禁用THREE.TrackballControls的默认缩放
    // 平移的速度，其默认值为0.3
    control.panSpeed = 3;
    // 是否禁用缩放，默认为false
    // control.noZoom = false;
    // 是否禁用平移，默认为false
    //@ts-ignore
    control.noPan = defaultData.mouse.RIGHT === THREE.MOUSE.ROTATE;
    // 是否禁用旋转，默认为false
    //@ts-ignore
    control.noRotate = defaultData.mouse.RIGHT === THREE.MOUSE.PAN;
    // 阻尼是否被禁用。默认为false
    control.staticMoving = true;
    // 阻尼的强度。仅在staticMoving设为false时考虑。默认为0.2
    // control.dynamicDampingFactor = 0.2;
    // 该数组包含用于控制交互的按键代码。
    // 当定义的第一个按键按下后，所有的鼠标交互（左/中/右键）表现为环绕。
    // 当定义的第二个按键按下后，所有的鼠标交互（左/中/右键）表现为缩放。
    // 当定义的第三个按键按下后，所有的鼠标交互（左/中/右键）表现为平移。
    // 默认为KeyA, KeyS, KeyD，分别表示A, S, D。
    // control.keys = ['KeyA', 'KeyS', 'KeyD'];
  }
  // 修改鼠标按键
  // 左键平移
  // control.mouseButtons.LEFT = defaultData.mouse.LEFT ?? THREE.MOUSE.PAN;
  control.mouseButtons.LEFT =
    //@ts-ignore
    defaultData.mouse.RIGHT === THREE.MOUSE.ROTATE
      ? THREE.MOUSE.PAN
      : THREE.MOUSE.ROTATE;
  // 滚轮滑动
  control.mouseButtons.MIDDLE = THREE.MOUSE.DOLLY;
  // 右键旋转
  //@ts-ignore
  control.mouseButtons.RIGHT = defaultData.mouse.RIGHT ?? THREE.MOUSE.ROTATE;
};
/**
 * 设置透视控制器
 * @param {OrbitControls|TrackballControls} perControl
 */
export const setPerspectiveControls = (
  perControl: OrbitControls | TrackballControls
) => {
  perspectiveControls = perControl;
};
export const setCameraType = (ct: number | string) => {
  cameraType = ct;
};

/**
 * 设置正交相机
 * @param {THREE.OrthographicCamera} ortCamera
 */
export const setOrthographicCamera = (ortCamera: THREE.OrthographicCamera) => {
  orthographicCamera = ortCamera;
};
/**
 * 设置坐标轴canvas
 * @param {HTMLCanvasElement}
 */
export const setArrowCanvas = (ac: HTMLCanvasElement) => {
  arrowCanvas = ac;
};

export const setCanvas = (c: HTMLCanvasElement) => {
  canvas = c;
};
 /**
     * 按名称获取组
     * @param {String} groupName
     */
export function  getGroupByName(groupName: string) {
    return scene?.getObjectByName(groupName);
  }
/**
 * 获取主画布
 * @return {HTMLCanvasElement}
 */
export const getCanvas = (): HTMLCanvasElement => {
  return canvas;
};
/**
 * 获取相机类型
 * @return {String}
 */
export const getCameraType = () => {
  return cameraType;
};
 /**
     * 获取当前相机
     * @return {THREE.OrthographicCamera|THREE.PerspectiveCamera}
     */
  export const  getCurrCamera=()=> {
    let camera;
    if (cameraType === "Orthographic") {
      camera = orthographicCamera;
    }
    if (cameraType === "Perspective") {
      camera = perspectiveCamera;
    }
    return camera;
  }
/**
 * 设置坐标轴renderer
 * @param {THREE.WebGLRenderer} ar
 */
export const setArrowRenderer = (ar: THREE.WebGLRenderer) => {
  arrowRenderer = ar;
};
/**
 * 获取正交控制器
 * @return {OrbitControls|TrackballControls}
 */
export const getOrthographicControls = () => {
  return orthographicControls;
};
/**
 * 获取主renderer
 * @return {THREE.WebGLRenderer}
 */
export const getRenderer = () => {
  return renderer;
};
/**
 * 获取坐标轴相机
 * @return {THREE.Camera}
 */
export const getArrowCamera = () => {
  return arrowCamera;
};

/**
 * 获取控件类型
 * @return {String}
 */
export const getControlType = () => {
  return controlType;
};
/**
 * 设置坐标轴场景
 * @param {THREE.Scene} as
 */
export const setArrowScene = (as: THREE.Scene) => {
  arrowScene = as;
};
/**
 * 获取坐标轴renderer
 * @return {THREE.WebGLRenderer}
 */
export const getArrowRenderer = () => {
  return arrowRenderer;
};
export const setArrowCamera = (ac: THREE.Camera) => {
  arrowCamera = ac;
};
/**
 * 设置正交控制器
 * @param {OrbitControls|TrackballControls} ortControl
 */
export const setOrthographicControls = (
  ortControl: OrbitControls | TrackballControls
) => {
  orthographicControls = ortControl;
};
/**
 * 创建控件
 * @param {THREE.OrthographicCamera|THREE.PerspectiveCamera} camera
 * @param {THREE.Vector3} camCenter
 */
export const createControl = (
  camera: THREE.Camera,
  camCenter: THREE.Vector3
):(OrbitControls|TrackballControls) => {
  debugger
  const renderer = getRenderer();

  // if (!camera || !renderer) return  ;

  let controls: IControl;
  let controlsBq: IBControl;
  if (getControlType() === ControlTypeEnum.Orbit) {
    // 创建轨道控件
    controls = new OrbitControls(camera, renderer.domElement);
    if (camCenter) controls.target = camCenter.clone(); // 围绕零件中心旋转
    initControlAttribute(controls, "OrbitControls");
    // addEventHandler(controls, 'change', this.onControlChange, true);
    controls.update();
    return controls;
  } else {
    // 创建轨迹球控件
    controlsBq = new TrackballControls(camera, renderer.domElement);
    if (camCenter) controlsBq.target = camCenter.clone(); // 围绕零件中心旋转
    initControlAttribute(controlsBq, "TrackballControls");
    // addEventHandler(controls, 'change', () => this.onControlChange(false), true);
    controlsBq.update();
    return controlsBq;
  }
};
/**
 *
 * 获取透视相机
 * @return {THREE.PerspectiveCamera}
 */
export const getPerspectiveCamera = () => {
  return perspectiveCamera;
};
/**
 * 设置透视相机
 * @param {THREE.PerspectiveCamera} perCamera
 */
export const setPerspectiveCamera = (perCamera: THREE.PerspectiveCamera) => {
  perspectiveCamera = perCamera;
};
/**
 * 获取坐标轴场景
 * @return {THREE.Scene}
 */
export const getArrowScene = () => {
  return arrowScene;
};
/**
 * 获取正交相机
 * @return {THREE.OrthographicCamera}
 */
export const getOrthographicCamera = () => {
  return orthographicCamera;
};
/**
 * 获取透视控制器
 * @return {OrbitControls|TrackballControls}
 */
export const getPerspectiveControls = () => {
  return perspectiveControls;
};
export const setScene = (s: THREE.Scene) => {
  scene = s;
};
export const setRenderer = (r: THREE.WebGLRenderer) => {
  renderer = r;
};
/**
 * 获取主场景
 * @return {THREE.Scene}
 */
export const getScene = () => {
  return scene;
};

/**
 * 设置控件类型
 * @param {String} ct, OrbitControls、TrackballControls
 */
export const setControlType = (ct: string) => {
  controlType = ct;
};
   /**
     * 按数组删除场景对象
     */
  export function  removeSceneObjByArray(childArray: any) {
       clearCacheByArray(childArray);
     removeSceneObj(childArray);
    }
export const mixinViewCommonFun = {
  methods: {
    /**
     * 设置主场景
     * @param {THREE.Scene} s
     */

    /**
     * 设置主画布
     * @param {HTMLCanvasElement} c
     */
    setCanvas(c: HTMLCanvasElement) {
      canvas = c;
    },

    /**
     * 获取主画布
     * @return {HTMLCanvasElement}
     */
    getCanvas() {
      return canvas;
    },

    /**
     * 设置主renderer
     * @param {THREE.WebGLRenderer} r
     */

    /**
     * 获取主renderer
     * @return {THREE.WebGLRenderer}
     */
    getRenderer() {
      return renderer;
    },

    /**
     * 设置坐标轴canvas
     * @param {HTMLCanvasElement} ac
     */
    setArrowCanvas(ac: HTMLCanvasElement) {
      arrowCanvas = ac;
    },

    /**
     * 获取坐标轴canvas
     * @return {HTMLCanvasElement}
     */
    getArrowCanvas() {
      return arrowCanvas;
    },

    /**
     * 设置坐标轴场景
     * @param {THREE.Scene} as
     */
    setArrowScene(as: THREE.Scene) {
      arrowScene = as;
    },

    /**
     * 获取坐标轴场景
     * @return {THREE.Scene}
     */
    getArrowScene() {
      return arrowScene;
    },

    /**
     * 设置坐标轴renderer
     * @param {THREE.WebGLRenderer} ar
     */
    setArrowRenderer(ar: THREE.WebGLRenderer) {
      arrowRenderer = ar;
    },

    /**
     * 获取坐标轴renderer
     * @return {THREE.WebGLRenderer}
     */
    getArrowRenderer() {
      return arrowRenderer;
    },

    /**
     * 设置坐标轴相机
     * @param {THREE.Camera} ac
     */
    setArrowCamera(ac: THREE.Camera) {
      arrowCamera = ac;
    },

    /**
     * 获取坐标轴相机
     * @return {THREE.Camera}
     */
    getArrowCamera() {
      return arrowCamera;
    },

    /**
     * 获取透视相机
     * @return {THREE.PerspectiveCamera}
     */
    getPerspectiveCamera() {
      return perspectiveCamera;
    },

    /**
     * 设置正交相机
     * @param {THREE.OrthographicCamera} ortCamera
     */
    setOrthographicCamera(ortCamera: THREE.OrthographicCamera) {
      orthographicCamera = ortCamera;
    },

    /**
     * 获取正交相机
     * @return {THREE.OrthographicCamera}
     */
    getOrthographicCamera() {
      return orthographicCamera;
    },

    /**
     * 设置透视控制器
     * @param {OrbitControls|TrackballControls} perControl
     */
    setPerspectiveControls(perControl: OrbitControls | TrackballControls) {
      perspectiveControls = perControl;
    },

    /**
     * 获取透视控制器
     * @return {OrbitControls|TrackballControls}
     */
    getPerspectiveControls() {
      return perspectiveControls;
    },

    /**
     * 获取正交控制器
     * @return {OrbitControls|TrackballControls}
     */
    getOrthographicControls() {
      return orthographicControls;
    },

    /**
     * 设置相机类型
     * @param {String} ct, Perspective、Orthographic
     */
    setCameraType(ct: number) {
      cameraType = ct;
    },

    /**
     * 获取相机类型
     * @return {String}
     */
    getCameraType() {
      return cameraType;
    },

    /**
     * 获取控件类型
     * @return {String}
     */
    getControlType() {
      return controlType;
    },

    /**
     * 设置相机中心
     * @param {THREE.Vector3} cc
     */
    setCameraCenter(cc: THREE.Vector3) {
      cameraCenter = cc;
    },

    /**
     * 获取相机类型
     * @return {THREE.Vector3}
     */
    getCameraCenter() {
      return cameraCenter;
    },

    /**
     * 获取场景所有体对象
     * @return {THREE.Object3D[]|*[]}
     */
    getSceneAllSolid() {
      return this.getSceneChildrenByCondition(SOLID_GROUP, (child) => child);
    },

    /**
     * 获取场景所有face对象
     * @return {THREE.Object3D[]|*[]}
     */
    getSceneAllFace() {
      return this.getSceneChildrenByCondition(FACE_GROUP, (child) => child);
    },

    /**
     * 获取场景所有wireframe对象
     * @return {THREE.Object3D[]|*[]}
     */
    getSceneAllWireframe() {
      return this.getSceneChildrenByCondition(
        WIREFRAME,
        (child) => child.isWireframe
      );
    },

    /**
     * 获取场景所有预设线对象
     * @return {THREE.Object3D[]|*[]}
     */
    getSceneAllYsLine(condition = () => true) {
      return this.getSceneChildrenByCondition(YS_LINE_GROUP, condition);
    },


    /**
     * 获取场景所有变径点对象
     * @return {THREE.Object3D[]|*[]}
     */
    getSceneAllPoint() {
      return this.getSceneChildrenByCondition(BJ_POINT_GROUP);
    },

    /**
     * 获取场景所有离散线对象
     * @return {THREE.Object3D[]|*[]}
     */
    getSceneAllDispersedLine() {
      return this.getSceneChildrenByCondition(DISPERSED_LINE_GROUP);
    },

    /**
     * 获取场景全部实体和全部线框
     * @returns {*[]}
     */
    getSceneAllSolidAndAllWireframe() {
      const solids = this.getSceneAllSolid();
      const wires = this.getSceneAllWireframe();
      return [...solids, ...wires];
    },

    /**
     * 获取场景所有面和所有线框
     * @returns {*[]}
     */
    getSceneAllFaceAndAllWireframe() {
      const faces = this.getSceneAllFace();
      const wires = this.getSceneAllWireframe();
      const points = this.getSceneAllPoint();
      return [...faces, ...wires, ...points];
    },

  

    /**
     * 按组属性获取场景子项
     * @param {String} groupAttr
     * @param {Function} condition
     * @return {THREE.Object3D[]|*[]}
     */
    getSceneChildrenByGroupAttr(
      groupAttr: string,
      condition = (child: object) => child
    ) {
      const group = scene.children.find(
        //@ts-ignore
        (child) => child && child instanceof THREE.Group && child?.[groupAttr]
      );
      if (!group) return [];
      return group.children.filter((child) => condition(child));
    },


   

    /**
     * 按条件获取场景对象
     * @param {String} namePrefix
     * @param {Boolean=} isGroup
     * @param {Function=} condition
     * @return {THREE.Object3D[]|*[]}
     */
    getSceneObjsByCondition(
      namePrefix: string,
      isGroup = true,
      condition = (child: object) => child
    ) {
      let objs: any[] = [];
      const meshArr = scene.children.filter((child) => {
        return (
          child &&
          ((isGroup &&
            child instanceof THREE.Group &&
            child.name?.startsWith(namePrefix)) ||
            //@ts-ignore
            (!isGroup && child.groupName?.startsWith(namePrefix)))
        );
      });
      for (const mesh of meshArr) {
        if (mesh instanceof THREE.Group) {
          objs.push(...mesh.children);
        } else {
          objs.push(mesh);
        }
      }
      objs = Array.from(new Set(objs));
      return objs.filter((child) => condition(child));
    },

 

    /**
     * 获取所有预设线对象及控制点对象
     * @return {{spheres: Array, ysLines: Array}}
     */
    getAllYsLineAndSpheres() {
      let ysLines: any[] = [];
      const ysLineGroup = this.getGroupByName(YS_LINE_GROUP);
      if (ysLineGroup) {
        ysLines = ysLineGroup.children.filter((child) => child);
      }
      //@ts-ignore
      const groupNames = ysLines
        .map((line) => line?.groupName)
        .filter((groupName) => groupName);
      const spheres = scene.children.filter((child: any) =>
        groupNames.includes(child.groupName)
      );
      return { ysLines, spheres };
    },

    /**
     * 创建控件
     * @param {THREE.OrthographicCamera|THREE.PerspectiveCamera} camera
     * @param {THREE.Vector3} camCenter
     */
    createControl(
      camera: THREE.OrthographicCamera | THREE.PerspectiveCamera,
      camCenter: THREE.Vector3
    ) {
      const renderer = this.getRenderer();

      if (!camera || !renderer) return;

      let controls: IControl;
      let controlsBq: IBControl;
      if (this.getControlType() === ControlTypeEnum.Orbit) {
        // 创建轨道控件
        controls = new OrbitControls(camera, renderer.domElement);
        if (camCenter) controls.target = camCenter.clone(); // 围绕零件中心旋转
        this.initControlAttribute(controls, "OrbitControls");
        // addEventHandler(controls, 'change', this.onControlChange, true);
        controls.update();
        return controls;
      } else {
        // 创建轨迹球控件
        controlsBq = new TrackballControls(camera, renderer.domElement);
        if (camCenter) controlsBq.target = camCenter.clone(); // 围绕零件中心旋转
        this.initControlAttribute(controlsBq, "TrackballControls");
        // addEventHandler(controls, 'change', () => this.onControlChange(false), true);
        controlsBq.update();
        return controlsBq;
      }
    },

    /**
     * 初始化控器制属性
     * @param {OrbitControls|TrackballControls} control
     * @param {String} type
     */
    initControlAttribute(
      control: IControl | IBControl,
      type = "OrbitControls"
    ) {
      if (type === "OrbitControls") {
        //@ts-ignore
        this.openAnimate = false;
        // OrbitControls attr
        // 使动画循环使用时阻尼或自转 意思是否有惯性
        control.enableDamping = false;
        // 是否可以缩放
        control.enableZoom = true;
        // 是否自动旋转
        control.autoRotate = false;
        // // 设置相机距离原点的最远距离
        // control.minDistance = 200;
        // // 设置相机距离原点的最远距离
        // control.maxDistance = 600;
        // 限制最大仰视角和俯视角
        control.minPolarAngle = 0; // 你能够垂直旋转的角度的下限，范围是0到Math.PI，其默认值为0
        control.maxPolarAngle = Math.PI; // 你能够垂直旋转的角度的上限，范围是0到Math.PI，其默认值为Math.PI
        // 是否开启右键拖拽
        //@ts-ignore
        control.enablePan = defaultData.mouse.RIGHT === THREE.MOUSE.PAN;
        // 否允许鼠标左键旋转场景
        //@ts-ignore
        control.enableRotate = defaultData.mouse.RIGHT === THREE.MOUSE.ROTATE;
      } else {
        //@ts-ignore
        this.openAnimate = true;
        // TrackballControls attr
        // 旋转的速度，其默认值为1.0
        control.rotateSpeed = 20.0;
        // 缩放的速度，其默认值为1.2
        //@ts-ignore
        control.zoomSpeed = defaultData.mouse.RIGHT === THREE.MOUSE.ROTATE ? 0 : 3;
        // control.zoomSpeed = 0.0; // 要实现自己的鼠标滚轮事件,必须禁用THREE.TrackballControls的默认缩放
        // 平移的速度，其默认值为0.3
        control.panSpeed = 3;
        // 是否禁用缩放，默认为false
        // control.noZoom = false;
        // 是否禁用平移，默认为false
        //@ts-ignore
        control.noPan = defaultData.mouse.RIGHT === THREE.MOUSE.ROTATE;
        // 是否禁用旋转，默认为false
        //@ts-ignore
        control.noRotate = defaultData.mouse.RIGHT === THREE.MOUSE.PAN;
        // 阻尼是否被禁用。默认为false
        control.staticMoving = true;
        // 阻尼的强度。仅在staticMoving设为false时考虑。默认为0.2
        // control.dynamicDampingFactor = 0.2;
        // 该数组包含用于控制交互的按键代码。
        // 当定义的第一个按键按下后，所有的鼠标交互（左/中/右键）表现为环绕。
        // 当定义的第二个按键按下后，所有的鼠标交互（左/中/右键）表现为缩放。
        // 当定义的第三个按键按下后，所有的鼠标交互（左/中/右键）表现为平移。
        // 默认为KeyA, KeyS, KeyD，分别表示A, S, D。
        // control.keys = ['KeyA', 'KeyS', 'KeyD'];
      }
      // 修改鼠标按键
      // 左键平移
      // control.mouseButtons.LEFT = defaultData.mouse.LEFT ?? THREE.MOUSE.PAN;
      control.mouseButtons.LEFT =
        //@ts-ignore
        defaultData.mouse.RIGHT === THREE.MOUSE.ROTATE
          ? THREE.MOUSE.PAN
          : THREE.MOUSE.ROTATE;
      // 滚轮滑动
      control.mouseButtons.MIDDLE = THREE.MOUSE.DOLLY;
      // 右键旋转
      //@ts-ignore
      control.mouseButtons.RIGHT = defaultData.mouse.RIGHT ?? THREE.MOUSE.ROTATE;
    },

   

   
    /**
     * 按组名获取对象
     * @return {THREE.Object3D[]}
     */
    getObjectByGroupName(groupName: string): THREE.Object3D[] {
      return scene.children.filter(
        (child: any) => child && child.groupName === groupName
      );
    },

    /**
     * 更新场景对象
     * @param {THREE.Object3D} object
     */
    updateSceneObject(object: any) {
      if (!object) return;
      scene.children.forEach((child: any) => {
        if (child.uuid === object.uuid) {
          for (const prop in object) {
            if (hasOwnProperty(object, prop) && hasOwnProperty(child, prop)) {
              child[prop] = object[prop];
            }
          }
        }
      });
    },

    /**
     * 设置face及边缘(轮廓)线可见
     * @param {Boolean} visible
     */
    setFaceAndEdgeVisible(visible: boolean) {
      const handler = (child: any) => {
        //@ts-ignore
        if (child.isFace || child.isSolid || this.isModelWireframe(child)) {
          child.visible = visible;
          child.needsUpdate = true;
        }
      };
      scene.children.forEach((child) => {
        if (child instanceof THREE.Group) {
          child.children.forEach((gChild) => handler(gChild));
        } else {
          handler(child);
        }
      });
      //@ts-ignore
      this.requestRender();
    },

    /**
     * 设置face可见
     * @param {Boolean} visible
     */
    setFaceVisible(visible: boolean) {
      const handler = (child: any) => {
        if (child.isFace || child.isSolid) {
          child.visible = visible;
          child.needsUpdate = true;
        }
      };
      scene.children.forEach((child) => {
        if (child instanceof THREE.Group) {
          child.children.forEach((gChild) => handler(gChild));
        } else {
          handler(child);
        }
      });
      //@ts-ignore
      this.requestRender();
    },

    /**
     * 设置边缘(轮廓)线可见
     * @param {Boolean} visible
     */
    setEdgeVisible(visible: boolean) {
      const handler = (child: any) => {
        //@ts-ignore
        if (this.isModelWireframe(child)) {
          child.visible = visible;
          child.needsUpdate = true;
        }
      };
      scene.children.forEach((child) => {
        if (child instanceof THREE.Group) {
          child.children.forEach((gChild) => handler(gChild));
        } else {
          handler(child);
        }
      });
      //@ts-ignore
      this.requestRender();
    },

    /**
     * 设置旋转角度
     * 参数是角度，角度0~360，弧度=角度*Math.PI/180
     * @param {String} axis
     * @param {Number} angle
     */
    rotate(axis: string, angle: number) {
      axis = axis.toLowerCase();
      const radian = (angle * Math.PI) / 180;
      scene.children.forEach((child: any) => {
     
        if (
          child instanceof THREE.Group ||
          (child instanceof THREE.Object3D && child.isEdge)
        ) {
          child.children.forEach((item: any) => {
            item.rotation[axis] = radian;
          });
        } else {
          if (child.isFace || child.isCurve) {
            child.rotation[axis] = radian;
          }
        }
        //@ts-ignore
        this.requestRender();
      });
    },

    /**
     * 上传图片
     * @return {Promise<void>}
     */
    async uploadImg(imgBase64: any, taskId: string) {
      const file = base64ToBlob(imgBase64, "");
      const fileName = taskId + ".png";
      const formData = new FormData();
      formData.append("taskId", taskId);
      formData.append("file", file, fileName);
      // const res = await updateThumbnail(formData, { loading: false });
      const res = {};
      logger.log("上传图片 res: ", res);
      return res;
    },

    /**
     * 屏幕截图
     * @param {String} taskId
     * @param {Boolean=} isInit
     * @param {Function=} customHandler
     */
    screenshot(taskId: any, isInit = false, customHandler = undefined) {
      //@ts-ignore
      if (this.submitScreenshot) return;
      //@ts-ignore
      this.submitScreenshot = true;
      logger.log("屏幕截图 taskId: ", taskId);
      const scene = this.getScene();
      const renderer = this.getRenderer();
      // render调用一次，表示渲染一帧
      //@ts-ignore
      renderer.render(scene, this.curCamera); // 此处renderer为three.js里的渲染器，scene为场景 camera为相机
      //@ts-ignore
      html2canvas(document.querySelector("#mainCanvas"), {
        // allowTaint: true,
        // windowWidth: 367 * 2,
        // windowHeight: 208 * 2,
      }).then(async (canvas) => {
        const imgData = canvas.toDataURL("image/png"); // 转换为base64数据
        if (customHandler) {
          //@ts-ignore
          customHandler(imgData);
          return;
        }
        if (isInit) {
          await this.uploadImg(imgData, taskId);
          //@ts-ignore
          this.submitScreenshot = false;
        } else {
          //@ts-ignore
          this.$modal.confirm({
            content: "是否把此次截图作为列表缩略图？",
            okText: "确定",
            cancelText: "仅下载",
            onOk: async () => {
              const res = await this.uploadImg(imgData, taskId);
              //@ts-ignore
              if (res?.success) {
                //@ts-ignore
                this.$message.info("设置缩略图成功");
              }
              //@ts-ignore
              this.submitScreenshot = false;
            },
            onCancel: () => {
              const fileName = taskId + ".png";
              downloadFileByNewWindow(imgData, fileName);
              //@ts-ignore
              this.submitScreenshot = false;
            },
          });
        }
      });
    },

    /**
     * 按组名删除对象，来自公共方法
     * @param {String} groupName
     * @param {Function=} conditionHandler
     */
    removeObjByGroupNameComeFromCommon(groupName: any, conditionHandler: any) {
      conditionHandler = conditionHandler ?? (() => true);
      const childArray = scene.children.filter(
        (child: any) =>
          child &&
          groupName &&
          child.groupName === groupName &&
          conditionHandler(child)
      );
     removeSceneObjByArray(childArray);
      //@ts-ignore
      this.requestRender();
    },

    /**
     * 清除绘制的曲线
     */
    clearDrawnCurve() {
      const group = this.getGroupByName(YS_LINE_GROUP);
      if (!group) return;
      // group.children.forEach((child) => {
      //   this.removeSceneYsLineByGroupName(child.nickname);
      // });
      // this.requestRender();
    },

    /**
     * 通过昵称清除绘制的曲线
     * @param {string} nickname
     */
    // clearDrawnCurveByNickname(nickname) {
    //   this.removeSceneYsLineByGroupName(nickname);
    // },

    /**
     * 清除绘制的变径点
     */
    clearDrawnBJPoint() {
      const group = this.getGroupByName(BJ_POINT_GROUP);
      if (!group) return;
      group.children = [];
      // this.requestRender();
    },

    /**
     * 按组删除场景对象
     */
    removeSceneObjByGroup(group: any) {
      if (group instanceof THREE.Group) {
       removeSceneObjByArray(group.children);
        group.clear();
        scene.remove(group);
      }
    },

 

    /**
     * 从拾取列表中删除指定模型并释放内存
     * @param {THREE.Object3D[]} raycasterObjs
     * @param {String} groupName
     */
    deleteRaycasterObjByGroupName(raycasterObjs: any, groupName: any) {
      const objs: any[] = [];
      raycasterObjs.forEach((raycasterObj: any) => {
        if (raycasterObj && groupName && raycasterObj.groupName === groupName) {
          this.deleteCacheByObj(raycasterObj);
         removeSceneObj(raycasterObj);
          raycasterObj = null;
        } else {
          objs.push(raycasterObj);
        }
      });
      return objs;
    },

    /**
     * 从拾取列表中删除所有模型并释放内存
     * @param {THREE.Object3D[]} raycasterObjs
     */
    clearRaycasterAll(raycasterObjs: any) {
      // 清理拾取对象
      if (raycasterObjs?.length) {
       removeSceneObjByArray(raycasterObjs);
        raycasterObjs.length = 0; // 清空列表
      }
    },

    /**
     * 从scene中删除所有模型并释放内存
     */
    clearSceneAll() {
      this.clearScene(scene);
    },

    /**
     * 从scene中删除模型并释放内存
     * @param {THREE.Scene} scene
     */
    clearScene(scene: any) {
      if (scene instanceof THREE.Scene) {
        const childArray = scene.children.filter((child) => child);
       removeSceneObjByArray(childArray);
        // this.requestRender();
      }
    },

    /**
     * 按数组清除缓存
     * @param {THREE.Object3D[]} children
     */
    clearCacheByArray(children: any) {
      if (children instanceof THREE.Group) {
        this.clearCacheByArray(children.children);
      }
      if (isArray(children)) {
        for (const child of children) {
          this.deleteCacheByObj(child);
        }
      }
    },

    /**
     * 按对象删除缓存
     * @param {THREE.Object3D} obj
     */
    deleteCacheByObj(obj: any) {
      if (obj instanceof THREE.Group) {
        this.deleteGroup(obj);
      }
      if (obj instanceof THREE.Mesh) {
        this.deleteMesh(obj);
      }
      if (obj instanceof THREE.Line || obj instanceof Line2) {
        this.deleteLine(obj);
      }
      if (obj instanceof THREE.Object3D && obj.children) {
        for (const child of obj.children) {
          this.deleteCacheByObj(child);
        }
      }
    },

    /**
     * 删除group，释放内存
     * @param {THREE.Group} group
     */
    deleteGroup(group: any) {
      if (!group) return;
      // 删除掉所有的模型组内的mesh
      group.traverse((item: any) => {
        this.deleteMesh(item);
      });
    },

    /**
     * 删除mesh，释放内存
     * @param {THREE.Mesh|THREE.Object3D} mesh
     */
    deleteMesh(mesh: THREE.Mesh | THREE.Object3D) {
      if (!mesh) return;
      // 删除掉模型内的mesh
      if (mesh instanceof THREE.Mesh) {
        if (isArray(mesh.material)) {
          mesh.material.forEach((m) => m.dispose());
        } else {
          mesh.material.dispose(); // 删除材质
        }
        mesh.geometry.dispose(); // 删除几何体
      }
    },

    /**
     * 删除line，释放内存
     * @param {THREE.Line|Line2} line
     */
    deleteLine(line: any) {
      if (!line) return;
      // 删除掉模型内的line2
      if (line instanceof THREE.Line || line instanceof Line2) {
        line.material.dispose(); // 删除材质
        line.geometry.dispose(); // 删除几何体
      }
    },

   

    /**
     * 删除场景内对象
     * @param {THREE.Mesh} object
     */
    deleteSceneObj(object: any) {
      if (!object) return;
      if (object.parent) {
        object.parent.remove(object);
      } else {
        scene.remove(object);
      }
    },

    /**
     * 清空渲染器缓存
     */
    clearRenderer() {
      this.clearScene(scene);
      if (renderer) {
        renderer.renderLists.dispose();
        renderer.dispose();
        renderer.forceContextLoss();
        //@ts-ignore
        renderer.domElement = null;
        //@ts-ignore
        renderer.content = null;
        //@ts-ignore
        renderer = null;
      }
    },

    /**
     * 清除坐标轴渲染器
     */
    clearAxesRenderer() {
      this.clearScene(arrowScene);
      if (arrowRenderer) {
        arrowRenderer.renderLists.dispose();
        arrowRenderer.dispose();
        arrowRenderer.forceContextLoss();
        //@ts-ignore
        arrowRenderer.domElement = null;
        //@ts-ignore
        arrowRenderer.content = null;
        //@ts-ignore
        arrowRenderer = null;
      }
    },

    /**
     * 注销场景
     */
    destroyScene() {
      scene?.clear();
    },
  },
};
